#include "opencv2/core/core.hpp"
#include "opencv2/core/internal.hpp"

//#include "cv.h"
#include "cascadeclassifier.h"

#include "cascadetrainer.h"
#include "SNCascadeClassifier.h"
#include "SNSimpleClassifier.h"
#include "SNLBPCalculator.h"
#include <stdint.h>
#include <QTime>
#include <QMessageBox>
using namespace std;
using namespace cv;
//-------------------------------------------------------------------------

void AddSample(SNTrainingClassifierSet& data, int x, int y, bool is_object)
{
	SNTrainingClassifierVector samples;

	SNTrainingClassifierSample sample;
	samples.Sign = is_object ? 1 : -1;

	sample.Value = x;
	samples.push_back(sample);

	sample.Value = y;
	samples.push_back(sample);

	data.push_back(samples);
}

CascadeTrainer::CascadeTrainer(QWidget *parent) : QWidget(parent)
{
	QTime t;
	
	cv::Mat image = cv::imread("test.bmp", 0);

	SNLBPCalculator calc;

	calc.Init(image);

	cv::Mat out = cv::Mat(image.rows, image.cols, CV_8UC4);

	t.restart();
	
	//for (int i = 0; i < 10; ++i)
	{
		calc.Calculate(image, out);

	}

	uint8_t b = *(out.data + 30 * out.cols + 30);

	int r = t.elapsed();

	QMessageBox::information(this, "", QString("%1").arg("%1").arg(r));
	
	return;
	SNSimpleClassifier SC;

	SNTrainingClassifierSet data;
	
	AddSample(data, 20, 35, false);
	AddSample(data, 31, 18, true);
	AddSample(data, 31, 32, false);
	AddSample(data, 30, 30, false);
	AddSample(data, 30, 40, false);
	AddSample(data, 35, 27, true);
	AddSample(data, 34, 48, false);
	AddSample(data, 39, 24, false);
	AddSample(data, 40, 34, false);
	AddSample(data, 45, 51, true);
	AddSample(data, 46, 19, false);
	AddSample(data, 46, 25, false);
	AddSample(data, 46, 55, true);
	AddSample(data, 48, 49, true);
	AddSample(data, 51, 46, true);
	AddSample(data, 46, 55, true);
	AddSample(data, 53, 41, true);
	AddSample(data, 57, 45, true);
	AddSample(data, 56, 55, false);
	AddSample(data, 59, 18, false);
	AddSample(data, 62, 37, true);
	AddSample(data, 64, 45, false);
	AddSample(data, 68, 36, true);
	AddSample(data, 70, 38, true);
	AddSample(data, 69, 44, true);


	/*AddSample(data, 0, 10, true);
	AddSample(data, 20, 10, false);

	AddSample(data, 0, 100, true);
	AddSample(data, 20, 50, false);

	AddSample(data, 0, 50, true);
	AddSample(data, 20, 100, false);
*/

	while (true)
	{
		SNTrainingClassifierSet data2;

		SNStrongCascadeClassifier strong;
		SC.StrongTrain(data, 16, strong);

		for (auto d : data)
		{
			int res = SC.Classify(d, strong);
			if (res == d.Sign && res == -1)
			{
			}
			else
			{
				data2.push_back(d);
			}
		}

		data = data2;
	}
}
//-------------------------------------------------------------------------

CascadeTrainer::~CascadeTrainer()
{

}
//-------------------------------------------------------------------------

void CascadeTrainer::Init(int argc, char *argv[])
{
	//CvCascadeClassifier classifier;

	//SNCascadeClassifier classifier;

	//string cascadeDirName, vecName, bgName;
	//int numPos = 2000;
	//int numNeg = 1000;
	//int numStages = 20;
	//int precalcValBufSize = 256,
	//	precalcIdxBufSize = 256;
	//bool baseFormatSave = false;

	//SNCascadeParams cascadeParams;
	//SNCascadeBoostParams stageParams;
	//Ptr<SNFeatureParams> featureParams[] = { Ptr<CvFeatureParams>(new CvHaarFeatureParams),
	//	Ptr<SNFeatureParams>(new SNLBPFeatureParams),
	//	Ptr<CvFeatureParams>(new CvHOGFeatureParams)
	//};

	//int fc = sizeof(featureParams) / sizeof(featureParams[0]);
	//if (argc == 1)
	//{
	//	cout << "Usage: " << argv[0] << endl;
	//	cout << "  -data <cascade_dir_name>" << endl;
	//	cout << "  -vec <vec_file_name>" << endl;
	//	cout << "  -bg <background_file_name>" << endl;
	//	cout << "  [-numPos <number_of_positive_samples = " << numPos << ">]" << endl;
	//	cout << "  [-numNeg <number_of_negative_samples = " << numNeg << ">]" << endl;
	//	cout << "  [-numStages <number_of_stages = " << numStages << ">]" << endl;
	//	cout << "  [-precalcValBufSize <precalculated_vals_buffer_size_in_Mb = " << precalcValBufSize << ">]" << endl;
	//	cout << "  [-precalcIdxBufSize <precalculated_idxs_buffer_size_in_Mb = " << precalcIdxBufSize << ">]" << endl;
	//	cout << "  [-baseFormatSave]" << endl;
	//	/*cascadeParams.printDefaults();
	//	stageParams.printDefaults();
	//	for (int fi = 0; fi < fc; fi++)
	//	featureParams[fi]->printDefaults();*/
	//	return ;
	//}

	//for (int i = 1; i < argc; i++)
	//{
	//	bool set = false;
	//	if (!strcmp(argv[i], "-data"))
	//	{
	//		cascadeDirName = argv[++i];
	//	}
	//	else if (!strcmp(argv[i], "-vec"))
	//	{
	//		vecName = argv[++i];
	//	}
	//	else if (!strcmp(argv[i], "-bg"))
	//	{
	//		bgName = argv[++i];
	//	}
	//	else if (!strcmp(argv[i], "-numPos"))
	//	{
	//		numPos = atoi(argv[++i]);
	//	}
	//	else if (!strcmp(argv[i], "-numNeg"))
	//	{
	//		numNeg = atoi(argv[++i]);
	//	}
	//	else if (!strcmp(argv[i], "-numStages"))
	//	{
	//		numStages = atoi(argv[++i]);
	//	}
	//	else if (!strcmp(argv[i], "-precalcValBufSize"))
	//	{
	//		precalcValBufSize = atoi(argv[++i]);
	//	}
	//	else if (!strcmp(argv[i], "-precalcIdxBufSize"))
	//	{
	//		precalcIdxBufSize = atoi(argv[++i]);
	//	}
	//	else if (!strcmp(argv[i], "-baseFormatSave"))
	//	{
	//		baseFormatSave = true;
	//	}
	//	else 
	//	if (cascadeParams.ScanAttr(argv[i], argv[i + 1])) 
	//	{ 
	//		i++; 
	//	}
	//	else
	//	if (stageParams.ScanAttr(argv[i], argv[i + 1])) 
	//	{ 
	//		i++; 
	//	}
	//	else if (!set)
	//	{
	//		for (int fi = 0; fi < fc; fi++)
	//		{
	//			if (featureParams[fi])
	//				set = featureParams[fi]->ScanAttr(argv[i], argv[i + 1]);
	//			
	//			if (!set)
	//			{
	//				i++;
	//				break;
	//			}
	//		}
	//	}
	//}

	/*classifier.Train(QString::fromStdString(cascadeDirName),
		QString::fromStdString(vecName),
		QString::fromStdString(bgName),
		numPos, numNeg,
		precalcValBufSize, precalcIdxBufSize,
		numStages,
		cascadeParams,
		*featureParams[cascadeParams.FeatureType],
		stageParams,
		baseFormatSave);*/
}
//-------------------------------------------------------------------------